package com.runvp.common.hex;

import com.runvp.common.util.enc.aes128gcm.HexStringToASCII;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.util.Locale;

@Slf4j
public class HexConvert {

    public static void main(String[] args) {
        String source = "41522355416828";
        System.out.println("原始数据：" + source);
        source = str2HexStr(source);
        System.out.println("转16进制字符串后：" + source);
        source = hexStr2Str(source);
        System.out.println("转回10进制字符串后：" + source);

        System.out.println("16进制转ascii ：" + HexStringToASCII.hexToAscii("7b22736e223a22383632333533303639393833393232222c227479223a317d"));
        System.out.println("16进制转10进制 ：" + hexStr2Str("34313434323734363233303037"));

        System.out.println("hexToDecimal=="+hexToDecimal("6000000007"));
        System.out.println("makeChecksum=="+makeChecksum("7703B2545052"));
        System.out.println("16进制数字转10进制数字:"+hexNumber2Ten("007A"));
        System.out.println("====="+hexNumber2TenStr("CDF7842B"));
        System.out.println("10进制数字转16进制数字:"+numberTen2Hex(18511));


        System.out.println(hexNumber2TenArr("02640000003137323238323533353531303636"));
        System.out.println(numberStr2HexStr("02"));
        System.out.println(new StringBuilder().append("01").append("4A000000").toString());
        System.out.println(toHexString("98BPRR4Wve41"));
        System.out.println("10进制转16进制 ：" + str2HexStr("98BPRR4Wve41"));
        System.out.println(hexStr2BinStr("7b22736e223a22383632333533303639393833393232222c227479223a317d"));
    }
    public static String hexStr2BinStr(String hexString){
        StringBuilder binaryBuilder = new StringBuilder();
        for (int i = 0; i < hexString.length(); i++) {
            char c = hexString.charAt(i);
            int decimal = Character.digit(c, 16); // 将字符转为对应的十进制整数
            String binary = Integer.toBinaryString(decimal); // 将十进制整数转为二进制字符串
            binaryBuilder.append(String.format("%4s", binary).replace(' ', '0')); // 每个十六进制字符转为4位二进制，并补齐前导零
        }
        String binary = binaryBuilder.toString();
        System.out.println(binary); // 输出二进制字符串
        return binary;
    }

    /**
     * 汉字转16进制
     * @param str
     * @return str
     */
    public static String toHexUnicode(String str) {
        String st = "";
        byte[] by = new byte[0];
        try {
            by = str.getBytes("gbk");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < by.length; i++) {
            String strs = Integer.toHexString(by[i]& 0XFF);
            st += strs.toUpperCase(Locale.ROOT);
        }
        return st;
    }
    /**
     * 字符串转化为Unicode编码
     */
    public static String string2Unicode(String string) {
        StringBuffer unicode = new StringBuffer();
        for (int i = 0; i < string.length(); i++) {
            // 取出每一个字符
            char c = string.charAt(i);
            // 转换为unicode
            unicode.append("\\u" + Integer.toHexString(c));
        }
        return unicode.toString();
    }
    /**
     * unicode 转字符串
     */
    public static String unicode2String(String unicode) {
        StringBuffer string = new StringBuffer();
        String[] hex = unicode.split("\\\\u");
        for (int i = 1; i < hex.length; i++) {
            // 转换出每一个代码点
            int data = Integer.parseInt(hex[i], 16);
            // 追加成string
            string.append((char) data);
        }
        return string.toString();
    }

    /**
     * 将一段错误解码的字符串重新解码
     */
    public static String convertEncodingFormat(String str, String formatFrom, String FormatTo) {
        String result = null;
        if (!(str == null || str.length() == 0)) {
            try {
                result = new String(str.getBytes(formatFrom), FormatTo);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
    /**
     * 高低位反转
     * @param str
     * @return str
     */
    public static String strTwoReversal(String str){
        StringBuilder reversalStr = new StringBuilder();
        int count = str.length() / 2;
        for (int i = count; i > 0; i--) {
            reversalStr.append(str.substring(i * 2 - 2, i * 2));
        }
        return reversalStr.toString();
    }
    /**
     * 字符串截取并转byte数组 十进制数据
     *
     * @param str
     * @return byte[]
     */
    public static byte[] buildByte(String str) {
        String head = str.substring(0, 7);
        System.out.println("前7位：" + head);
        String body1 = str.substring(7, 7 + 10);
        System.out.println("中间位1：" + body1);
        String body2 = str.substring(7 + 10, str.length() - 3);
        System.out.println("中间位2：" + body2);
        String foot = str.substring(str.length() - 3, str.length());
        System.out.println("最后3位：" + foot);
        byte[] headByte = head.getBytes();
        byte[] bodyByte1 = str2Byte(body1);
        byte[] bodyByte2 = new byte[]{(byte) Integer.parseInt(body2)};
        byte[] footByte = foot.getBytes();
        byte[] all = byteMergerAll(headByte, bodyByte1, bodyByte2, footByte);
        return all;
    }

    /**
     * 累加校验和 -获得一组十六进制串依次累加，不需要空格，累加之后取低字节
     */

    public static String makeChecksum(String data) {
//        log.info("makeChecksum data :{}", data);
        if (data == null || data.equals("")) {
            return "";
        }
        int total = 0;
        int len = data.length();
        int num = 0;
        while (num < len) {
            String s = data.substring(num, num + 2);
            total += Integer.parseInt(s, 16);
            num = num + 2;
        }
        /**
         * 用256求余最大是255，即16进制的FF
         */
        int mod = total % 256;
        String hex = Integer.toHexString(mod);
        len = hex.length();
        // 如果不够校验位的长度，补0,这里用的是两位校验
        if (len < 2) {
            hex = "0" + hex;
        }
        return hex.toUpperCase();
    }

    /* Convert byte[] to hex string.这里我们可以将byte转换成int，然后利用Integer.toHexString(int)来转换成16进制字符串。
     * @param src byte[] data
     * @return hex string
     */
    public static String bytesToHexString(byte[] src) {
        if (src == null || src.length <= 0) {
            return null;
        }
        StringBuilder stringBuilder = new StringBuilder("");
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    /**
     * 字符串转byte[]
     *
     * @param code
     * @return byte[]
     */
    public static byte[] str2Byte(String code) {
        if (StringUtils.isBlank(code)) {
            return null;
        }
        byte[] bytes = new byte[code.length() / 2];
        for (int i = 0; i < code.length() / 2; i++) {
            bytes[i] = Byte.parseByte(code.substring(i * 2, i * 2 + 2));
        }
        return bytes;
    }

    /**
     * 多个byte[]合并
     *
     * @param values
     * @return byte[]
     */
    public static byte[] byteMergerAll(byte[]... values) {
        int length_byte = 0;
        for (int i = 0; i < values.length; i++) {
            if (null == values[i]) {
                continue;
            }
            length_byte += values[i].length;
        }
        byte[] all_byte = new byte[length_byte];
        int countLength = 0;
        for (int i = 0; i < values.length; i++) {
            byte[] b = values[i];
            if (null == values[i]) {
                continue;
            }
            System.arraycopy(b, 0, all_byte, countLength, b.length);
            countLength += b.length;
        }
        return all_byte;
    }

    /**
     * 16进制字符串转10进制字符串
     *
     * @param: [hex]
     * @return: int
     * @description: 按位计算，位值乘权重
     */
    public static int hexToDecimal(String hex) {
        int outcome = 0;
        for (int i = 0; i < hex.length(); i++) {
            char hexChar = hex.charAt(i);
            outcome = outcome * 16 + charToDecimal(hexChar);
        }
        return outcome;
    }

    /**
     * @param: [c]
     * @return: int
     * @description:将字符转化为数字
     */
    public static int charToDecimal(char c) {
        if (c >= 'A' && c <= 'F')
            return 10 + c - 'A';
        else
            return c - '0';
    }
    /**
     * 十六进制数字转十进制数字字符串
     *
     * @return str
     */
    public static byte[] hexNumber2TenArr(String numStr) {
        byte[] bytes = new byte[numStr.length() / 2];
        if (StringUtils.isBlank(numStr)) {
            return bytes;
        }
        if (numStr.length() % 2 != 0) {
            return bytes;
        }
        for (int i = 0; i < numStr.length() / 2; i++) {
            bytes[i] = (byte) Integer.parseInt(hexNumber2Ten(numStr.substring(i * 2, i * 2 + 2)));
        }
        return bytes;
    }
    /**
     * 10进制数字转16进制数字字符串
     *
     * @param bytes
     * @return str
     */
    public static String numberStr2HexStr(byte[] bytes) {
        if(null == bytes){
            return "";
        }
        String str = HexConvert.bytesToHexString(bytes);
        return str.toUpperCase();
    }
    /**
     * 10进制数字转16进制数字字符串
     *
     * @param str
     * @return str
     */
    public static String numberStr2HexStr(String str) {
        if (null == str) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length() / 2; i++) {
            sb.append(numberTen2Hex(Integer.parseInt(str.substring(i * 2, i * 2 + 2))));
        }
        return sb.toString().toUpperCase();
    }
    /**
     * 字符串转换成为16进制(无需Unicode编码)
     *
     * @param str
     * @return
     */
    public static String str2HexStr(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
//             sb.append(' ');
        }
        return sb.toString().trim();
    }
    public static String toHexString(String s) {
        String str = "";
        for (int i = 0; i < s.length(); i++) {
            int ch = (int) s.charAt(i);
            String s4 = Integer.toHexString(ch);
            str = str + s4;
        }
        return "0x" + str;//0x表示十六进制
    }

    /**
     * 16进制直接转换成为字符串(无需Unicode解码)
     *
     * @param hexStr
     * @return str
     */
    public static String hexStr2Str(String hexStr) {
        try{
            String str = "0123456789ABCDEF";
            char[] hexs = hexStr.toCharArray();
            byte[] bytes = new byte[hexStr.length() / 2];
            int n;
            for (int i = 0; i < bytes.length; i++) {
                n = str.indexOf(hexs[2 * i]) * 16;
                n += str.indexOf(hexs[2 * i + 1]);
                bytes[i] = (byte) (n & 0xff);
            }
            return new String(bytes);
        }catch (Exception e){
            log.error("hexStr2Str:::error:{}",e);
            return "";
        }
    }

    /**
     * 十六进制数字转十进制数字字符串
     *
     * @return str
     */
    public static String hexNumber2TenStr(String numStr) {
        if (StringUtils.isBlank(numStr)) {
            return "";
        }
        if (numStr.length() % 2 != 0) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < numStr.length()/2; i++) {
            sb.append(hexNumber2Ten(numStr.substring(i * 2, i * 2 + 2)));
        }
        return sb.toString();
    }

    /**
     * 十六进制数字转十进制数字
     *
     * @param numStr
     * @return 十进制数字
     */
    public static String hexNumber2Ten(String numStr) {
        String ret = String.valueOf(Long.parseLong(numStr, 16));
        if (ret.length() < 2 || ret.length()%2 != 0) {
            return "0" + ret;
        }
        return ret;
    }

    /**
     * byte to int
     *
     * @param b
     * @return int
     */
    public static int byte2Int(byte b) {
        if (b < 0) {
            return 100 - b;
        }
        return b;
    }

    /**
     * number 10 to 16
     *
     * @param numb
     * @return String
     */
    public static String numberTen2Hex(Integer numb) {
        if (null == numb) {
            return "";
        }
        String hex = Integer.toHexString(numb);
        if (hex.length() % 2 != 0) {
            hex = "0" + hex;
        }
        return hex.toUpperCase();
    }
    /**
     * number 10 to 16
     *
     * @param numb
     * @return String
     */
    public static String numberTen2Hex(Long numb) {
        if (null == numb) {
            return "";
        }
        String hex = Long.toHexString(numb);
        if (hex.length() < 2) {
            hex = "0" + hex;
        }
        return hex.toUpperCase();
    }
}

